home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 26
/
Cream of the Crop 26.iso
/
os2
/
which213.zip
/
src
/
which.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-06-03
|
29KB
|
957 lines
/*---------------------------------------------------------------------------
which.c
This program by default finds the path of an executable command under
either OS/2 or MS-DOS. It can also be used to find data files in the
DPATH or DLLs in the LIBPATH (at least under OS/2). It does not have
a whole lot of error-checking, but the array sizes are reasonably gen-
erous.
To do: add support for ksh, bash, etc.; allow wildcard commands?
Copyright (c) 1993 by Greg Roelofs. 4OS2/4DOS spawnl() code by Michael
D. Lawler. DosQuerySysInfo() code by Kenneth Porter. You may use this
code for any purpose whatsoever, as long as you don't sell it and don't
claim to have written it. Not that you'd want to.
Modified by Wonkoo Kim (wkim+@pitt.edu):
(The original starting version was v2.1)
v2.1.1 September 15, 1995
- Wildcard support (for emx/gcc) is added.
- Added option: -s Show file size and date.
v2.1.2 January 14, 1996
- Added options:
-h Search *.hlp in HELP dir.
-b Search *.inf in BOOKSHELF dir.
-e * Search dirs set by env vars.
v2.1.3 June 3, 1997
- Option -l now searches BEGINLIBPATH + LIBPATH + ENDLIBPATH.
(Thanks to "Bruce A. Mallett" <bam@NightStorm.com>)
- New options:
-1 Show only the first match from all command line args, i.e.
displays a single path name if found (useful in makefile)
(-1 + -a for all first matches of command line args)
-u Unix style path names (use forward slashes as dir separators)
- Minor refinements
---------------------------------------------------------------------------*/
#define VERSION "v2.1.3 June-03-1997 updated by Wonkoo Kim"
/* #define DEBUG */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <process.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#ifndef TRUE
# define TRUE 1
# define FALSE 0
#endif
/* not used:
#if defined(__OS2__) && !defined(OS2)
# define OS2
#endif
*/
#if defined(__IBMC__)
# define S_IFMT 0xF000 /* or (S_IFREG | S_IFDIR | S_IFCHR) */
#endif
#ifndef S_ISDIR
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
#if defined(__IBMC__) || defined(__EMX__) || defined(__WATCOMC__)
# ifndef __32BIT__
# define __32BIT__
# endif
# define INCL_DOSMISC /* for IBM Toolkit headers */
# define INCL_DOSERRORS /* for IBM Toolkit headers */
# define INCL_NOPMAPI /* for IBM Toolkit headers */
# include <os2.h>
#if defined(__EMX__)
# include <fnmatch.h> /* for wildcard support -- Wonkoo Kim */
#endif
#endif
#ifdef DEBUG
# define Trace(x) fprintf x
#else
# define Trace(x)
#endif
int get_libpath(char **path);
int get_helppath(char **path);
int get_bookpath(char **path);
int printmsg (char *msg, int pos);
void pretty_path (char *path, char dir_sep);
struct stat statbuf;
/* extensions must be in order of operating-system precedence! */
static char *ext_command[] = { /* COMMAND extensions */
".com",
".exe",
".bat"
};
static char *ext_cmd[] = { /* CMD extensions */
".com",
".exe",
".cmd",
".bat"
};
static char *ext_4dos[] = { /* 4DOS extensions */
".com",
".exe",
".btm",
".bat"
};
static char *ext_4os2[] = { /* 4OS2 extensions */
".com",
".exe",
".btm",
".cmd",
".bat"
};
static char *ext_libpath[] = { /* LIBPATH extension(s) */
".dll"
};
static char *ext_dpath[] = { /* DPATH extension(s) */
".boo",
".dat",
".inf",
".ini", /* does this belong here? */
".hlp",
".msg",
".ndx"
};
static char *ext_helppath[] = { /* HELP extension(s) */
".hlp"
};
static char *ext_bookpath[] = { /* BOOKSHELF extension(s) */
".inf"
};
static char *ext_envpath[] = { /* ENV extension(s) */
".*"
};
/* OS/2 internal commands: some of these are rarely used outside of
* command files, but all of them can be called from the command line.
* (I don't know if some of the OS/2-only commands might be in later
* versions of MS-DOS. One could use spawnl() and check the errors,
* but that would be slow.)
*/
static char *int_command[] = {
"call", "cd", "chdir", "cls", "copy", "date", "del", "dir", "echo",
"erase", "exit", "for", "goto", "if", "md", "mkdir", "path", "pause",
"prompt", "rd", "rem", "ren", "rename", "rmdir", "set", "shift",
"time", "type", "ver", "verify", "vol"
};
static char *int_cmd[] = {
/* note that extproc cannot be called from command line in 4OS2 */
"chcp", "detach", "dpath", "endlocal", "extproc", "keys", "move",
"setlocal", "start",
/* all the rest are identical to int_command[] */
"call", "cd", "chdir", "cls", "copy", "date", "del", "dir", "echo",
"erase", "exit", "for", "goto", "if", "md", "mkdir", "path", "pause",
"prompt", "rd", "rem", "ren", "rename", "rmdir", "set", "shift",
"time", "type", "ver", "verify", "vol"
};
typedef struct shellinfo {
char *name;
char **extension;
int num_ext;
char **internal;
int num_int;
} SHELLINFO;
/* these guys must match the order of shells[] */
#define _COMMAND 0
#define _CMD 1
#define _4DOS 2
#define _4OS2 3
#define _4OS2_16 4
#define _4OS2_32 5
SHELLINFO shells[] = {
{"COMMAND.COM", ext_command, sizeof(ext_command)/sizeof(char *),
int_command, sizeof(int_command)/sizeof(char *) },
{"CMD.EXE", ext_cmd, sizeof(ext_cmd)/sizeof(char *),
int_cmd, sizeof(int_cmd)/sizeof(char *) },
{"4DOS.COM", ext_4dos, sizeof(ext_4dos)/sizeof(char *),
(char **)NULL, 0 },
{"4OS2.EXE", ext_4os2, sizeof(ext_4os2)/sizeof(char *),
(char **)NULL, 0 },
{"4OS2-16.EXE", ext_4os2, sizeof(ext_4os2)/sizeof(char *),
(char **)NULL, 0 },
{"4OS2-32.EXE", ext_4os2, sizeof(ext_4os2)/sizeof(char *),
(char **)NULL, 0 }
};
#define REGPATH 0 /* for pathtype */
#define LIBPATH 1
#define DPATH 2
#define HELPPATH 3
#define BOOKPATH 4
#define ENVPATH 5
char *prognam;
/****************/
/* Main program */
/****************/
int main(int argc, char *argv[])
{
static char tempname[1024];
char *p, *q, *comspec, *path, *pathvar="", *dir[1000];
int i, j, k, c, error=0, startdir=0;
int sh=_CMD, all=FALSE, pathtype=REGPATH, regpath=TRUE, fourshell=FALSE;
int firstmatch=FALSE;
int numdirs=0, numshells=sizeof(shells)/sizeof(SHELLINFO);
int showinfo=FALSE, quiet=FALSE;
int found = 0;
char info[20];
char *envpath = "", envvar[100];
char dir_separator = '\\'; /* OS/2 or DOS style dir separator */
/*---------------------------------------------------------------------------
Parse the command line...
---------------------------------------------------------------------------*/
#ifdef __EMX__
prognam = _getname (argv[0]); /* remove pathname */
#else
prognam = argv[0];
#endif
p = prognam - 1;
while (*++p)
*p = tolower(*p); /* assumes "smart" tolower() */
if (argc <= 1)
--argc;
else
while (--argc > 0 && (*++argv)[0] == '-')
while ((c = *++(argv[0])) != '\0')
switch (c) {
case 'a': /* list all matches */
all = TRUE;
break;
case 'l': /* search for DLLs */
pathtype = LIBPATH;
break;
case 'd': /* search for data files */
pathtype = DPATH;
break;
case 'h': /* search for help files */
pathtype = HELPPATH;
break;
case 'b': /* search for book files */
pathtype = BOOKPATH;
break;
case 'e': /* search files in paths set by env */
pathtype = ENVPATH;
if (*++(argv[0])) {
strcpy (envvar, argv[0]);
envpath = getenv(envvar);
*(argv[0]+1) = '\0';
} else if (--argc > 0 && (*++argv)[0]) {
strcpy (envvar, argv[0]);
envpath = getenv(envvar);
*(argv[0]+1) = '\0';
} else
error++;
break;
case '1': /* find the first match of all cmd args */
firstmatch = TRUE;
break;
case 's': /* show file information */
showinfo = TRUE;
break;
case 'q': /* quite mode (return errlevel) */
quiet = TRUE;
break;
case 'u': /* unix style path (forward slashes) */
dir_separator = '/';
break;
default:
++error;
break;
} /* end switch, while, while, if */
/*---------------------------------------------------------------------------
Print usage if any errors or if no arguments.
---------------------------------------------------------------------------*/
if (error || ((pathtype == REGPATH) && (argc <= 0))) {
#ifdef TRADITIONAL
fprintf(stderr, "%s: too few arguments\n", prognam);
#else
fprintf(stderr, "\n"
"which (%s) for OS/2%s, from Newtware\n\n"
"Usage: %s [options] [cmd ... ]\n\n"
"Options:\n"
" (default behavior is to find location of program executed as \"cmd\")\n"
" -1 show the first match from all cmd args; display nothing if not found\n"
" -a list all matches (With -1, list all first matches of cmd args)\n"
" -b search directories in BOOKSHELF for book (.inf) files%s\n"
" -d search directories in DPATH for data files%s\n"
" -e search directories in a given env var; Exapmple: -e EPMPATH\n"
" -h search directories in HELP for help (.hlp) files%s\n"
" -l search directories in LIBPATH (BEGIN/ENDLIBPATH) for DLLs%s\n"
" -q quiet mode (only returns error code without onscreen messages)\n"
" -s show file date/time and size\n"
" -u unix style path names (use forward-slashes as dir separators)\n\n"
" cmd name to be searched (wildcards can be used)\n\n"
"Examples: %s -las emx*\n"
" %s -las foo*.bar (override the default extension)\n"
, VERSION,
#if defined(__32BIT__) && !defined(EMX)
"", prognam, "", "", "", "",
#else
" & DOS", prognam, " (OS/2)", " (OS/2)", " (OS/2)", " (OS/2)",
#endif /* ?__32BIT__ */
prognam, prognam);
#endif /* ?TRADITIONAL */
exit(1);
}
/*---------------------------------------------------------------------------
Try to figure out what shell we're in, based on COMSPEC.
---------------------------------------------------------------------------*/
if ((comspec = getenv("COMSPEC")) == (char *)NULL || *comspec == '\0') {
Trace((stderr, "COMSPEC is empty...assuming COMSPEC = cmd.exe\n"));
sh = _CMD;
} else {
Trace((stderr, "COMSPEC = %s\n", comspec));
if ((p = strrchr (comspec, '\\')))
p++;
else if ((p = strrchr (comspec, '/')))
p++;
else
p = comspec;
for (i = 0; i < numshells; ++i) {
if (stricmp(p, shells[i].name) == 0) {
sh = i;
break;
}
}
if (i == numshells) {
sh = _CMD;
fprintf(stderr,
"%s: unknown command shell \"%s\"\n%s: assuming %s\n",
prognam, comspec, prognam, shells[sh].name);
}
if (sh >= 2 && sh <= 5) /* 4DOS, 4OS2, 4OS2-16, 4OS2-32 */
fourshell = TRUE;
}
Trace((stderr, "shell is %s\n\n", shells[sh].name));
/*---------------------------------------------------------------------------
Get the PATH, DPATH or LIBPATH, depending on the user's wishes.
---------------------------------------------------------------------------*/
/* for regular path, current directory is always implied; not for others */
switch (pathtype) {
case REGPATH:
pathvar = "PATH";
regpath = TRUE;
dir[numdirs++] = ".";
path = getenv(pathvar);
break;
case DPATH:
pathvar = "DPATH";
regpath = FALSE;
shells[sh].extension = ext_dpath;
shells[sh].num_ext = sizeof(ext_dpath)/sizeof(char *);
path = getenv(pathvar);
break;
case LIBPATH:
pathvar = "LIBPATH";
regpath = FALSE;
shells[sh].extension = ext_libpath;
shells[sh].num_ext = sizeof(ext_libpath)/sizeof(char *);
get_libpath(&path);
break;
case HELPPATH:
pathvar = "HELP";
regpath = FALSE;
shells[sh].extension = ext_helppath;
shells[sh].num_ext = sizeof(ext_helppath)/sizeof(char *);
path = getenv(pathvar);
break;
case BOOKPATH:
pathvar = "BOOKSHELF";
regpath = FALSE;
shells[sh].extension = ext_bookpath;
shells[sh].num_ext = sizeof(ext_bookpath)/sizeof(char *);
path = getenv(pathvar);
break;
case ENVPATH:
pathvar = envvar;
regpath = FALSE;
shells[sh].extension = ext_envpath;
shells[sh].num_ext = sizeof(ext_envpath)/sizeof(char *);
path = envpath;
break;
}
Trace((stderr, "COMSPEC now = %s\n", comspec));
if (argc <= 0) {
printf ("%s=%s\n", pathvar, path);
exit (0);
}
/*---------------------------------------------------------------------------
Terminate the path elements and store pointers to each one.
---------------------------------------------------------------------------*/
if (path == (char *)NULL || *path == '\0') {
Trace((stderr, "\n%s is empty\n\n", pathvar));
if (!regpath) {
fprintf(stderr, "%s: %s is empty\n", prognam, pathvar);
exit (2);
}
} else {
pretty_path (path, dir_separator);
Trace((stderr, "\n%s = %s\n\n", pathvar, path));
if (*path != ';')
dir[numdirs++] = path;
p = path - 1;
while (*++p)
if (*p == ';') {
*p = '\0';
if ((p[1] != '\0') && (p[1] != ';'))
dir[numdirs++] = p + 1;
} else
*p = tolower(*p); /* should probably make this an option... */
}
/*---------------------------------------------------------------------------
If we're doing a normal PATH search under 4OS2 or 4DOS, check the path
for a "." entry; if find one, ignore the extra "." entry which was previ-
ously inserted at the beginning of the dir[] array. (Entries of the form
"d:." don't count, and CMD and COMMAND always insert the "." first.)
---------------------------------------------------------------------------*/
if (fourshell && pathtype == REGPATH) {
for (i = 1; i < numdirs; ++i)
if (dir[i][0] == '.' && dir[i][1] == '\0') { /* "." */
startdir = 1;
break;
}
}
/*---------------------------------------------------------------------------
For each command or file given as an argument, check all of the direc-
tories in the appropriate path. For commands, first see if it's an in-
ternal command or (in the case of 4DOS/4OS2) an alias; if not, search
the path for it. For each directory in the path, see if the OS will con-
sider it a command as is (it has a dot in its name), and if so whether
it exists; then try appending each extension (in order of precedence)
and again check for existence. For data files or DLLs, just check direc-
tories in the path for the filename or the filename with an appropriate
extension (".dll", ".inf", etc.) appended.
---------------------------------------------------------------------------*/
for (j = 0; j < argc; ++j) {
int hasdot;
int pos=0;
#ifdef __EMX__
int wildcard;
char **list;
int l;
wildcard = (strchr(argv[j], (int)'?') != (char *)NULL) ||
(strchr(argv[j], (int)'*') != (char *)NULL);
#endif
/* don't bother with internal commands if argument has a dot */
hasdot = (strchr(argv[j], (int)'.') != (char *)NULL);
if (!quiet && j) {
if (! firstmatch)
printf ("\n");
else if (found && ! showinfo)
printf (" ");
}
found = 0;
if (regpath && !hasdot) {
Trace((stderr, " checking %s internals\n", shells[sh].name));
/* 4DOS/4OS2 have tests for internals/aliases, so check smartly */
if (fourshell) {
char *tempenv[2] = {tempname, NULL};
int rc;
#ifdef COMMANDSEP_WORKS /* This form always fails (get correct response only
* if first condition is true, i.e., both alias and
* internal command). It appears to be another bug
* in 4OS2 (rc always = 0). The line is too long for
* 4DOS in any case (257 bytes for 5-char alias name).
*/
sprintf(tempname, "4WHICH=iff isalias %s .and. isinternal %s "
"then %%+ echos %s: aliased to \"%%@alias[%s]\" %%+ exit 43 %%+"
" elseiff isalias %s then %%+ echos %s: aliased to \"%%@alias"
"[%s]\" %%+ exit 42 %%+ elseiff isinternal %s then %%+ exit 41 "
"%%+ else %%+ exit 40 %%+ endiff", argv[j], argv[j],
argv[j], argv[j], argv[j], argv[j], argv[j], argv[j]);
Trace((stderr, "4WHICH length = %d bytes\n\n%s\n\n",
strlen(tempname), tempname));
rc = spawnle(P_WAIT, comspec, comspec, "/c", "%4which%", NULL,
tempenv);
Trace((stderr, "4WHICH return code = %d\n", rc));
#else /* !COMMANDSEP_WORKS */
/* quotes around alias necessary due to 4DOS/4OS2 bug */
if (sh != _4DOS) { /* 4OS2: can do in one long command */
sprintf(tempname, "4WHICH=iff isalias %s .and. isinternal "
"%s then & echos %s: aliased to \"%%@alias[%s]\" & exit "
"43 & elseiff isalias %s then & echos %s: aliased to "
"\"%%@alias[%s]\" & exit 42 & elseiff isinternal %s then "
"& exit 41 & else & exit 40 & endiff", argv[j], argv[j],
argv[j], argv[j], argv[j], argv[j], argv[j], argv[j]);
Trace((stderr, "4WHICH length = %d bytes\n\n%s\n\n",
strlen(tempname), tempname));
/* "/c", "4which" arguments must be separate for emx+gcc */
rc = spawnle(P_WAIT, comspec, comspec, "/c", "%4which%",
NULL, tempenv);
Trace((stderr, "4WHICH return code = %d\n", rc));
if (rc == 42 || rc == 43) /* alias (and internal if 43) */
++found;
} else {
sprintf(tempname, "4WHICH=iff isalias %s .and. isinternal "
"%s then ^ exit 43 ^ elseiff isalias %s then ^ exit 42 ^ "
"elseiff isinternal %s then ^ exit 41 ^ else ^ exit 40 ^ "
"endiff", argv[j], argv[j], argv[j], argv[j]);
Trace((stderr, "4WHICH length = %d bytes\n\n%s\n\n",
strlen(tempname), tempname));
rc = spawnle(P_WAIT, comspec, comspec, "/c", "%4which%", NULL,
tempenv);
Trace((stderr, "4WHICH return code = %d\n", rc));
if (rc == 42 || rc == 43) { /* alias */
++found;
sprintf(tempname, "echos %s: aliased to \"%%@alias"
"[%s]\"", argv[j], argv[j]);
Trace((stderr, "2nd cmd length = %d bytes\n\n%s\n\n",
strlen(tempname), tempname));
spawnl(P_WAIT, comspec, comspec, "/c", tempname, NULL);
}
}
#endif /* ?COMMANDSEP_WORKS */
if (rc == 41 || (rc == 43 && all && !firstmatch)) { /* internal */
++found;
sprintf(tempname, "%s internal command", shells[sh].name);
if (rc == 41)
printf("%s: %s", argv[j], tempname);
else
printf(" (also %s", tempname);
}
} else {
/* quit as soon as found: only one internal match allowed */
for (i = 0; i < shells[sh].num_int; ++i) {
Trace((stderr, " checking %s\n", shells[sh].internal[i]));
#ifdef __EMX__
if (wildcard) {
if (fnmatch(argv[j], shells[sh].internal[i],
_FNM_IGNORECASE|_FNM_OS2) == 0) {
found++;
if (quiet) break;
if (showinfo) {
printf("%4d: %s:%*s %s internal command\n",
found, shells[sh].internal[i],
8-(int)strlen(shells[sh].internal[i]), "",
shells[sh].name);
} else {
sprintf(tempname, "%s: %s internal command",
shells[sh].internal[i], shells[sh].name);
if (found == 2) {
pos = printmsg (" (also ", -pos);
pos = printmsg (tempname, -pos);
} else {
pos = printmsg (tempname, pos);
}
}
if (!all || firstmatch)
break; /* quit right now unless finding all */
}
} else {
#endif
if (stricmp(argv[j], shells[sh].internal[i]) == 0) {
++found;
if (quiet) break;
if (showinfo) {
printf("%4d: %s:%*s %s internal command\n",
found, argv[j], 8-(int)strlen(argv[j]), "",
shells[sh].name);
} else {
printf("%s:%*s %s internal command\n",
argv[j], 8-(int)strlen(argv[j]), "",
shells[sh].name);
}
break;
}
#ifdef __EMX__
}
#endif
}
}
}
for (i = startdir; (i < numdirs) && (!found || (all && !firstmatch)); ++i) {
p = tempname;
q = dir[i];
while ((*p++ = *q++) != '\0'); /* p now points to char *after* 0 */
if (p[-2] == '\\' || p[-2] == '/') /* could be root dir (e.g., c:\) */
--p;
p[-1] = dir_separator; /* replace null with dir sep. */
q = argv[j];
while ((*p++ = *q++) != '\0'); /* copy program name */
--p; /* point at null */
if (hasdot) {
Trace((stderr, " checking %s\n", tempname));
#ifdef __EMX__
list = _fnexplode (tempname);
if (list) {
for (l = 0; list[l] != NULL; ++l) {
if (!stat(list[l], &statbuf) && !S_ISDIR(statbuf.st_mode)) {
found++;
if (quiet) break;
if (showinfo) {
strftime (info, 20, "%T %D",
localtime(&statbuf.st_mtime));
printf ("%4d: %s %9ld %s\n", found, info,
statbuf.st_size, list[l]);
} else {
if (found == 2) {
pos = printmsg (" (also ", -pos);
pos = printmsg (list[l], -pos);
} else
pos = printmsg (list[l], pos);
}
if (!all || firstmatch)
break; /* quit right now unless finding all */
}
}
_fnexplodefree (list);
}
#else
if (!stat(tempname, &statbuf) && !S_ISDIR(statbuf.st_mode)) {
++found;
if (quiet) break;
if (showinfo) {
strftime (info, 20, "%T %D",
localtime(&statbuf.st_mtime));
printf ("%4d: %s %9ld %s\n", found, info,
statbuf.st_size, tempname);
} else {
if (found == 2) {
pos = printmsg (" (also ", -pos);
pos = printmsg (tempname, -pos);
} else
pos = printmsg (tempname, pos);
}
if (!all || firstmatch)
break; /* quit right now unless finding all */
}
#endif
}
for (k = 0; (k < shells[sh].num_ext) && (!found || (all && !firstmatch)); ++k) {
strcpy(p, shells[sh].extension[k]);
Trace((stderr, " checking %s\n", tempname));
#ifdef __EMX__
list = _fnexplode (tempname);
if (list) {
for (l = 0; list[l] != NULL; ++l) {
if (!stat(list[l], &statbuf) && !S_ISDIR(statbuf.st_mode)) {
found++;
if (quiet) break;
if (showinfo) {
strftime (info, 20, "%T %D",
localtime(&statbuf.st_mtime));
printf ("%4d: %s %9ld %s\n", found, info,
statbuf.st_size, list[l]);
} else {
if (found == 2) {
pos = printmsg (" (also ", -pos);
pos = printmsg (list[l], -pos);
} else
pos = printmsg (list[l], pos);
}
if (!all || firstmatch)
break; /* quit right now unless finding all */
}
}
_fnexplodefree (list);
}
#else
if (!stat(tempname, &statbuf) && !S_ISDIR(statbuf.st_mode)) {
++found;
if (quiet) break;
if (showinfo) {
strftime (info, 20, "%T %D",
localtime(&statbuf.st_mtime));
printf ("%4d: %s %9ld %s\n", found, info,
statbuf.st_size, tempname);
} else {
if (found == 2) {
pos = printmsg (" (also ", -pos);
pos = printmsg (tempname, -pos);
} else
pos = printmsg (tempname, pos);
}
if (!all || firstmatch)
break; /* quit right now unless finding all */
}
#endif
}
} /* end i-loop */
if (quiet) {
if (!found) exit (1);
} else {
if (!found && !firstmatch) {
printf("%s is NOT FOUND in:\n ", argv[j]);
pos = -1;
for (i = 0; i < numdirs; ++i) {
pos = printmsg (dir[i], pos);
}
}
if (!showinfo && found > 1) {
if (pos < 75)
printf (") %d\n", found);
else {
printf (")\n %d\n", found);
}
}
if (firstmatch && found && !all) break;
}
}
exit (0);
}
/**************************/
/* Function get_libpath() */
/**************************/
int get_libpath(char **path)
{
char *line, *s, *p, config_sys[]="c:\\config.sys";
char *libpath[3];
int i, len;
int foundcfg=FALSE;
#ifdef __32BIT__
int drive;
APIRET rc;
#endif
FILE *cfg=NULL;
*path = (char *)NULL;
#ifdef __EMX__
if (_osmode == DOS_MODE) {
return -1;
}
#endif
if ((line = (char *)malloc(4096)) == NULL) {
fprintf(stderr, "%s: not enough memory\n", prognam);
exit(8);
}
#ifdef __32BIT__
rc = DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &drive, sizeof(drive));
if (rc == NO_ERROR) {
config_sys[0] = drive - 1 + 'a';
if (!stat(config_sys, &statbuf) && !S_ISDIR(statbuf.st_mode) &&
(cfg = fopen(config_sys, "r")) != NULL)
foundcfg = TRUE;
} else {
fprintf(stderr, "%s: internal error (%ld)\n", prognam, rc);
#endif
if (!stat(config_sys+2, &statbuf) && !S_ISDIR(statbuf.st_mode) &&
(cfg = fopen(config_sys+2, "r")) != NULL)
foundcfg = TRUE;
else if (!stat(config_sys, &statbuf) && !S_ISDIR(statbuf.st_mode) &&
(cfg = fopen(config_sys, "r")) != NULL)
foundcfg = TRUE;
#ifdef __32BIT__
}
#endif
libpath[1] = (char *)NULL; /* Assume no libpath present */
if (foundcfg) {
/* assume cfg is open file pointer to config.sys */
while (fgets((s = line), 4096, cfg)) {
while (*s == ' ') s++; /* remove leading blanks */
if (strnicmp(s, "LIBPATH", 7) == 0) {
/* get rid of trailing newline, if any */
if ((p=strrchr(s, '\n')) != NULL)
*p = '\0';
Trace((stderr, "found LIBPATH line:\n%s\n", line));
p = strchr(s+7, '=');
if (p != NULL) {
while (*++p == ' ') ;
libpath[1] = p;
}
break;
}
}
fclose (cfg);
}
/*
* Here with libpath[1] either null (because no LIBPATH was found in a config.sys
* file) or pointing into line[] to the start of the path data. Now to grab the
* begin and end libpaths, allocate a buffer large enough for all of them, and
* glue the whole thing together in the appropriate order.
*/
#ifdef __32BIT__
libpath[0] = malloc (512);
libpath[2] = malloc (512);
if (!libpath[0] || !libpath[2]) {
fprintf (stderr, "No memory!\n");
exit (8);
}
*libpath[0] = '\0';
*libpath[2] = '\0';
rc = DosQueryExtLIBPATH (libpath[0], BEGIN_LIBPATH);
if (rc != NO_ERROR)
fprintf (stderr, "Error %ld (0x%0lx) obtaining BEGINLIBPATH!\n", rc, rc);
rc = DosQueryExtLIBPATH (libpath[2], END_LIBPATH);
if (rc != NO_ERROR)
fprintf (stderr, "Error %ld (0x%0lx) obtaining ENDLIBPATH!\n", rc, rc);
#else
/* Getting libpaths by getenv() is not best, but try ... */
libpath[0] = getenv ("BEGINLIBPATH");
libpath[2] = getenv ("ENDLIBPATH");
#endif
len = 0;
for (i = 0; i < 3; ++i ) {
if (libpath[i] && *libpath[i])
len += strlen (libpath[i]) + 1; /* extra space for a semicolon */
}
if (len == 0) { /* no library path */
#ifdef __32BIT__
free (libpath[0]);
free (libpath[2]);
#endif
return (-1);
}
p = malloc (len + 1);
if (! p) {
fprintf (stderr, "No memory!\n");
exit (8);
}
*path = p;
for (i = 0; i < 3; i++) { /* merge library paths */
if (libpath[i] && *libpath[i]) {
strcpy (p, libpath[i]);
p += strlen (p);
if (p[-1] != ';') *p++ = ';';
}
}
*p = '\0'; /* Terminate the path */
#ifdef __32BIT__
free (libpath[0]);
free (libpath[2]);
#endif
return (0);
}
/*--------------------------------------------------------------------------*/
int printmsg (char *msg, int pos)
/*--------------------------------------------------------------------------*/
/* Smartly print msg at the column pos with comma-and-space delimited
* if the msg can fit in the 80-column screen width, and return the next
* column postion to be printed. If msg would bump to screen border, msg is
* printed at the next line after a space.
*/
{
int mode;
mode = pos;
if (mode > 0) {
printf (",");
pos++;
} else if (mode < 0) {
pos = -pos;
}
pos += strlen(msg);
if (pos >= 78) { /* if not fit in screen */
if (mode) /* if previous pos was not zero */
printf ("\n");
pos = strlen(msg);
}
if (mode > 0) {
printf (" ");
pos++;
}
printf ("%s", msg);
return (pos);
}
/*----------------------------------------------------------------------*/
void pretty_path (char *path, char dir_sep)
/*----------------------------------------------------------------------*/
/* convert path to either unix style or OS/2 (DOS) style */
{
char bad_sep;
switch (dir_sep) {
case '\\':
bad_sep = '/';
break;
case '/':
bad_sep = '\\';
break;
default:
return;
break;
}
for ( ; *path; path++) {
if (*path == bad_sep) *path = dir_sep;
}
}